#include <memory>

#include "TcpServer.hpp"
#include "Log.hpp"
#include "NetCal.hpp"
#include "Sevice.hpp"

using namespace log_ns;

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cerr << "Usage " << argv[0] << " Server-ip Server-port" << std::endl;
        exit(0);
    }

    std::string server_ip = argv[1];
    uint16_t server_port = std::stoi(argv[2]);

    SockSPtr sock = std::make_shared<TcpSocket>();
    if (!sock->BuildClientSocket(server_ip, server_port))
    {
        LOG(ERROR, "connect error\n");
        exit(1);
    }
    srand(time(nullptr) ^ getpid());
    const std::string opers = "+-*/%";

    std::string packagestreamqueue;
    while (true)
    {
        // 构建数据
        int x = rand() % 10;
        usleep(x * 1000);
        int y = rand() % 10;
        usleep(y * 1000);
        char oper = opers[y % opers.size()];

        // 构建请求
        auto req = Factory::BuildRequestDefault();
        req->SetValue(x, y, oper);

        // 1. 序列化
        std::string reqstr;
        req->Serialize(&reqstr);

        // 2. 添加长度报头字段
        reqstr = Encode(reqstr);

        std::cout << "-----------------------------------------" << std::endl;
        LOG(INFO, "request string : %s \n", reqstr.c_str());

        // 3. 发送数据
        sock->Send(reqstr);

        while (true) // 反复读，直到读到一个完整报文并处理完成
        {
            // 4. 读取应答，response
            ssize_t n = sock->Recv(&packagestreamqueue);
            if (n <= 0)
            {
                break;
            }
            // 5. 报文解析，提取报头和有效载荷
            std::string package = Decode(packagestreamqueue);
            if (package.empty())
                continue;
            LOG(INFO, "package : %s \n", package.c_str());

            // 6. 反序列化
            auto resp = Factory::BuildResponseDefault();
            resp->Deserialize(package);

            // 7. 打印结果
            resp->PrintResult();

            break;
        }

        sleep(1);
    }

    sock->Close();
    return 0;
}